﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Kawanon.Usability;
using Kawanon.Usability.Visualization;
using Microsoft.Win32;
using System.Diagnostics;
using QTPlugin;
using System.Reflection;
using Kawanon.Sessions;
using Kawanon.BandExtension;
using Kawanon.Localization;

namespace Kawanon.QtHoney
{
	public partial class OptionsForm : Form
	{
		private static Dictionary<Type, string[]> s_tags = new Dictionary<Type, string[]>();

		static OptionsForm()
		{
			/*
			s_tags.Add(typeof(GestureInformation), new string[] {
				"Gesture.Enabled",
				"Gesture.DrawTrails",
				"Gesture.PreferGestureTrack",
			});
			*/
			s_tags.Add(typeof(SessionManagerInformation), new string[] {
				"SessionManager.SkipAlreadyExists",
				"SessionManager.CloseOldTabs",
			});
		}

		private IPluginServer m_server;
		private Dictionary<Type, object> m_informations = new Dictionary<Type, object>();

		public int SelectedTabIndex
		{
			get
			{
				for (int i = 0; i < toolStrip1.Items.Count; i++)
				{
					ToolStripItem item = (ToolStripItem)toolStrip1.Items[i];
					if(!(item is ToolStripButton)){
						continue;
					}
					if (((ToolStripButton)item).Checked)
					{
						return i;
					}
				}
				return -1;
			}
			set
			{
				toolStrip1.Items[value].PerformClick();
			}
		}

		public OptionsForm(IPluginServer server)
		{
			InitializeComponent();

			m_server = server;
			expressionsView1.Server = server;

			propertyGrid1.ContextMenuStrip = Utility.CreateContextMenuStrip(propertyGrid1);

			StringResource.Apply("OptionsForm_Text", this);
			StringResource.Apply(MessageBoxButtons.OKCancel, buttonOk, buttonCancel);
			StringResource.Apply("OptionsForm_ToolBar", toolStrip1.Items);
			StringResource.Apply("OptionsForm_ListView_Groups", listView1.Groups);
			StringResource.Apply("OptionsForm_ListView", listView1.Items);
		}

		private ListViewItem FindItemByTag(ListView.ListViewItemCollection c, object tag)
		{
			foreach (ListViewItem item in c)
			{
				if (tag.Equals(item.Tag))
				{
					return item;
				}
			}
			return null;
		}

		private void SyncCheck(string key, object info, bool storing)
		{
			ListViewItem item = FindItemByTag(listView1.Items, key);
			if (item == null)
			{
				return;
			}

			string[] tokens = key.Split('.');
			PropertyInfo prop = info.GetType().GetProperty(tokens[tokens.Length - 1]);
			if (storing)
			{
				prop.SetValue(info, item.Checked, null);
			}
			else
			{
				bool b = (bool)prop.GetValue(info, null);
				item.Checked = b;
			}
		}

		private void SyncInformation(Type t, bool storing)
		{
			object info = GetRegisteredInformation(t);
			string[] keys = s_tags[t];
			foreach (string key in keys)
			{
				SyncCheck(key, info, storing);
			}

			//NOTE: m_informations にまかせる
			//if (storing)
			//{
			//    Persistence.SaveInformation(info, false);
			//}
		}

		private void SyncCheck(string key, bool storing, bool defaultValue)
		{
			RegistryKey reg = Plugins.OpenRegistryKey(storing);
			if (reg != null)
			{
				ListViewItem item = FindItemByTag(listView1.Items, key);
				if (storing)
				{
					reg.SetValue(key, item.Checked, RegistryValueKind.DWord);
				}
				else
				{
					object obj = reg.GetValue(key);
					if (obj == null)
					{
						obj = defaultValue;
					}
					item.Checked = Convert.ToBoolean(obj);
				}
				reg.Close();
			}
		}

		private void SyncCheck(string key, bool storing)
		{
			SyncCheck(key, storing, false);
		}

		private void OptionsForm_Load(object sender, EventArgs e)
		{
			//RegistryKey key = Plugins.OpenRegistryKey(false);
			//if (key == null)
			//{
			//    return;
			//}

			//ListViewItem[] items = new ListViewItem[listView1.Items.Count];
			//listView1.Items.CopyTo(items, 0);
			//string[] names = Array.ConvertAll(items, item => (string)item.Tag);
			//foreach (ListViewItem item in listView1.Items)
			//{
			//    string name = (string)item.Tag;
			//    item.Checked = Convert.ToBoolean(key.GetValue(name, item.Checked));
			//}

			//SyncInformation(typeof(GestureInformation), false);
			SyncInformation(typeof(SessionManagerInformation), false);

			SyncCheck("DebugMode", false);
			SyncCheck("RegisterToSystemMenu", false, true);

			//toolStripTextBox_MinimumDistance.Text = info.MinimumDistance.ToString();
		}

		private void OptionsForm_FormClosed(object sender, FormClosedEventArgs e)
		{
			if (this.DialogResult != DialogResult.OK)
			{
				return;
			}

			ValidateChildren();

			//SyncInformation(typeof(GestureInformation), true);
			SyncInformation(typeof(SessionManagerInformation), true);

			//foreach (ListViewItem item in listView1.Items)
			//{
			//    string name = (string)item.Tag;
			//    key.SetValue(name, item.Checked, RegistryValueKind.DWord);
			//}

			SyncCheck("DebugMode", true);
			SyncCheck("RegisterToSystemMenu", true);

			//if (toolStripTextBox_MinimumDistance.Tag != null)
			//{
			//    info.MinimumDistance = (uint)toolStripTextBox_MinimumDistance.Tag;
			//}

			expressionsView1.Save();
			languageView1.Save();

			foreach (object obj in m_informations.Values)
			{
				Persistence.SaveInformation(obj, false);
			}
			Plugins.NotifySettingsChanged();
		}

		private void toolStripButton_Export_Click(object sender, EventArgs e)
		{
			SaveFileDialog dlg = new SaveFileDialog();
			dlg.Title = StringResource.Localize(MiscResources.ExportSettingsTitle);
			dlg.FileName = "QTHoney.reg";
			dlg.Filter = StringResource.Localize(MiscResources.ExportSettingsFilter);

			DialogResult res = dlg.ShowDialog(this);
			if (res == DialogResult.Cancel)
			{
				return;
			}

			RegistryKey key = Plugins.OpenRegistryKey(false);
			if (key == null)
			{
				return;
			}
			string regPath = key.ToString();
			key.Close();

			ProcessStartInfo si = new ProcessStartInfo();
			si.FileName = "regedit";
			si.Arguments = String.Format("/e \"{0}\" \"{1}\"", dlg.FileName, regPath);

			try
			{
				Process proc = Process.Start(si);
				proc.WaitForExit();
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message,
					StringResource.Localize(Caption.Error, false),
					MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		private void toolStripButton_Expressions_Click(object sender, EventArgs e)
		{
			//GestureForm form = new GestureForm(m_server);
			//form.ShowDialog(this);

			//NOTE: SelectView 内の view.Visible = true でどうしても ListView のゴミが見えてしまうので
			expressionsView1.ListView.Hide();

			ToggleViewButton((ToolStripButton)sender, expressionsView1);

			expressionsView1.ListView.Show();
		}

		private void toolStripButton_About_Click(object sender, EventArgs e)
		{
			AboutForm form = new AboutForm();
			form.ShowDialog();
		}

		private object GetRegisteredInformation(Type t)
		{
			object info = null;
			if (!m_informations.TryGetValue(t, out info))
			{
				info = Persistence.GetInformation(t);

				m_informations[t] = info;
			}
			return info;
		}

		//private void SwitchView()
		//{
		//    bool b = propertyGrid1.Visible || expressionsView1.Visible;
		//    listView1.Visible = b;
		//    propertyGrid1.Visible = !b;
		//    expressionsView1.Visible = !b;
		//}

		private void SelectView(Control c)
		{
			c.Dock = DockStyle.Fill;
			//c.Visible = true;

			Control[] views = new Control[] { listView1, propertyGrid1, expressionsView1, languageView1 };
			foreach (Control view in views)
			{
				//if (c != view)
				//{
				//    view.Visible = false;
				//}
				view.Visible = (c == view);
			}
		}

		private void SelectViewObject(Type t)
		{
			object info = GetRegisteredInformation(t);
			propertyGrid1.SelectedObject = info;

			SelectView(propertyGrid1);
		}

		private void ToggleViewButton(ToolStripButton button, MethodInvoker fun)
		{
			//UseWaitCursor = true;
			//SuspendLayout();

			if (button.Checked)
			{
				SelectView(listView1);
			}
			else
			{
				fun();
			}

			ToolStripButton[] buttons = new ToolStripButton[] {
				toolStripButton_Expressions,
				toolStripButton_Gesture,
				toolStripButton_Rendering,
				toolStripButton_AddressBar,
				toolStripButton_Language
			};
			foreach (ToolStripButton button2 in buttons)
			{
				if (button != button2)
				{
					button2.Checked = false;
				}
			}
			button.Checked = !button.Checked;

			this.Text = button.Checked
				? button.ToolTipText
				: StringResource.Localize("OptionsForm_Text", 0, false);

			//ResumeLayout();
			//UseWaitCursor = false;
		}

		private void ToggleViewButton(ToolStripButton button, Type t)
		{
			ToggleViewButton(button, delegate()
			{
				SelectViewObject(t);
			});
		}

		private void ToggleViewButton(ToolStripButton button, Control c)
		{
			ToggleViewButton(button, delegate()
			{
				SelectView(c);
			});
		}

		private void toolStripButton_Gesture_Click(object sender, EventArgs e)
		{
			//Utility.EditInformation<GestureInformation>(this, "マウスジェスチャの詳細設定", null);
			ToggleViewButton((ToolStripButton)sender, typeof(GestureInformation));
		}

		private void toolStripButton_Rendering_Click(object sender, EventArgs e)
		{
			//Utility.EditInformation<RenderingInformation>(this, "描画の設定", Resource.RenderingInformation);
			ToggleViewButton((ToolStripButton)sender, typeof(RenderingInformation));
		}

		private void toolStripButton_AddressBar_Click(object sender, EventArgs e)
		{
			//Utility.EditInformation<AddressBarInformation>(this, "アドレスバーの設定", null);
			ToggleViewButton((ToolStripButton)sender, typeof(AddressBarInformation));
		}

		private void toolStripButton_Language_Click(object sender, EventArgs e)
		{
			ToggleViewButton((ToolStripButton)sender, languageView1);
		}

		private void buttonOk_Click(object sender, EventArgs e)
		{
			// ShowDialog を通して表示されなかった場合、明示的に閉じる
			this.DialogResult = DialogResult.OK;
			Close();
		}

		private void buttonCancel_Click(object sender, EventArgs e)
		{
			this.DialogResult = DialogResult.Cancel;
			Close();
		}

	}
}
